﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Web;
using System.IO;
using Microsoft.IdentityModel.Protocols.WSTrust;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Security.Principal;
using System.Xml;
using SlamCms.SharePointServices.Configuration;


namespace SlamCms.SharePointServices.Authentication
{
	internal static class Credentials
	{
		private static NetworkCredential _networkCredential;

		internal static NetworkCredential NetworkCredential
		{
			get
			{	
				if (_networkCredential == null)
				{	
					_networkCredential = CredentialCache.DefaultNetworkCredentials;

					if (!String.IsNullOrEmpty(ConfigurationManager.Environment.NetworkCredential.UserName))
					{
						if (String.IsNullOrEmpty(ConfigurationManager.Environment.NetworkCredential.Domain))
						{
							_networkCredential = new NetworkCredential(ConfigurationManager.Environment.NetworkCredential.UserName, ConfigurationManager.Environment.NetworkCredential.Password);
						}
						else
						{
							_networkCredential = new NetworkCredential(ConfigurationManager.Environment.NetworkCredential.UserName, ConfigurationManager.Environment.NetworkCredential.Password, ConfigurationManager.Environment.NetworkCredential.Domain);
						}
					}
				}
				return _networkCredential;
			}
		}

		private static Cookie _fedAuthCookie;

		internal static Cookie FedAuthCookie
		{
			get
			{
				if (_fedAuthCookie == null || _fedAuthCookie.Expired)
				{
					string authenticateUrl = ConfigurationManager.Environment.DefaultApplication.AdminUrl.TrimEnd('/') + "/_layouts/Authenticate.aspx?Source=%2F";
					string trustUrl = ConfigurationManager.Environment.TrustedIdentityProvider.SamlServerUrl.TrimEnd('/') + "/_trust/";
					string adfsUrl = ConfigurationManager.Environment.TrustedIdentityProvider.StsServerUrl.TrimEnd('/') + "/adfs/services/trust/13/windowstransport";

					RequestSecurityToken rst = new RequestSecurityToken();
					rst.RequestType = WSTrust13Constants.RequestTypes.Issue;

					rst.AppliesTo = new EndpointAddress(trustUrl);
					rst.KeyType = WSTrust13Constants.KeyTypes.Bearer;


					WSTrust13RequestSerializer trustSerializer = new WSTrust13RequestSerializer();
					WSHttpBinding binding = new WSHttpBinding();

					binding.Security.Mode = SecurityMode.Transport;

					binding.Security.Message.ClientCredentialType = MessageCredentialType.None;
					binding.Security.Message.EstablishSecurityContext = false;

					binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
					EndpointAddress address = new EndpointAddress(adfsUrl);
					WSTrust13ContractClient trustClient = new WSTrust13ContractClient(binding, address);

					trustClient.ClientCredentials.Windows.AllowNtlm = true;
					trustClient.ClientCredentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
					trustClient.ClientCredentials.Windows.ClientCredential = CredentialCache.DefaultNetworkCredentials;
					System.ServiceModel.Channels.Message response =
						trustClient.EndIssue(trustClient.BeginIssue(
						System.ServiceModel.Channels.Message.CreateMessage(
						//MessageVersion.Default, WSTrustFeb2005Constants.Actions.Issue, 
						MessageVersion.Default, WSTrust13Constants.Actions.Issue,

						new TrustClientRequestBodyWriter(trustSerializer, rst)), null, null));
					trustClient.Close();

					XmlDictionaryReader reader = response.GetReaderAtBodyContents();
					string stsResponse = reader.ReadOuterXml();

					//generate response to Sharepoint
					string stringData = String.Format("wa=wsignin1.0&wctx={0}&wresult={1}",
						HttpUtility.UrlEncode(authenticateUrl),
						HttpUtility.UrlEncode(stsResponse));
					HttpWebRequest sharepointRequest = HttpWebRequest.Create(trustUrl) as HttpWebRequest;
					sharepointRequest.Method = "POST";
					sharepointRequest.ContentType = "application/x-www-form-urlencoded";
					sharepointRequest.CookieContainer = new CookieContainer();
					sharepointRequest.AllowAutoRedirect = false;
					Stream newStream = sharepointRequest.GetRequestStream();

					byte[] data = Encoding.UTF8.GetBytes(stringData);
					newStream.Write(data, 0, data.Length);
					newStream.Close();
					HttpWebResponse webResponse = sharepointRequest.GetResponse() as HttpWebResponse;

					_fedAuthCookie = new Cookie("FedAuth", webResponse.Cookies["FedAuth"].Value);
					_fedAuthCookie.Expires = DateTime.Now.AddHours(1);
					_fedAuthCookie.Path = "/";
					_fedAuthCookie.Secure = true;
					_fedAuthCookie.HttpOnly = true;

					Uri samlUri = new Uri(ConfigurationManager.Environment.DefaultApplication.AdminUrl.TrimEnd('/'));
					_fedAuthCookie.Domain = samlUri.Host;
				}

				return _fedAuthCookie;
			}
		}
	}
}
